{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 拉格朗日插值代码"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# 导入数据分析库Pandas和拉格朗日插值函数\n",
    "import pandas as pd\n",
    "from scipy.interpolate import lagrange\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "           A         B         C\n",
      "0   235.8333  324.0343  478.3231\n",
      "1   236.2708  325.6379  515.4564\n",
      "2   238.0521  328.0897  517.0909\n",
      "3   235.9063       NaN  514.8900\n",
      "4   236.7604  268.8324       NaN\n",
      "5        NaN  404.0480  486.0912\n",
      "6   237.4167  391.2652  516.2330\n",
      "7   238.6563  380.8241       NaN\n",
      "8   237.6042  388.0230  435.3508\n",
      "9   238.0313  206.4349  487.6750\n",
      "10  235.0729       NaN       NaN\n",
      "11  235.5313  400.0787  660.2347\n",
      "12       NaN  411.2069  621.2346\n",
      "13  234.4688  395.2343  611.3408\n",
      "14  235.5000  344.8221  643.0863\n",
      "15  235.6354  385.6432  642.3482\n",
      "16  234.5521  401.6234       NaN\n",
      "17  236.0000  409.6489  602.9347\n",
      "18  235.2396  416.8795  589.3457\n",
      "19  235.4896       NaN  556.3452\n",
      "20  236.9688       NaN  538.3470\n"
     ]
    }
   ],
   "source": [
    "# 输入输出数据路径，使用Excel格式\n",
    "inputfile = '../Data/missing_data.xls'\n",
    "outputfile = '../Data/Temp/lagrange_missing_data_processed.xls'\n",
    "\n",
    "# 读入数据\n",
    "data = pd.read_excel(inputfile, header=None, names=['A', 'B', 'C'])\n",
    "\n",
    "# 打印原始数据\n",
    "print(data)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(5, 0), (12, 0), (3, 1), (10, 1), (19, 1), (20, 1), (4, 2), (7, 2), (10, 2), (16, 2)]\n"
     ]
    }
   ],
   "source": [
    "# 判断DataFrame中空值的位置（行，列）\n",
    "NULL_value_position = []\n",
    "for j in range(len(data.columns)):\n",
    "    value_column = data[data.columns[j]].isnull()\n",
    "    for i in range(len(value_column)):\n",
    "        if value_column[i]==True:\n",
    "            NULL_value_position.append((i, j))\n",
    "print(NULL_value_position)\n",
    "\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "## 拉格朗日插值\n",
    "\n",
    "首先从原始数据集中确定因变量和自变量，取出缺失值前后5个数据（前后数据中遇到数据不存在或者为空的，直接将数据舍去，将仅有的数据组成一组），根据取出来的10个数据组成一组。然后采用拉格朗日多项式插值公式\n",
    "\n",
    "$$ L_n{(x)}=\\sum_{i=1}^n{l_i}{(x)}{y_i} $$\n",
    "\n",
    "其中，x为缺失值对应的下标序号，$L_n{(x)}$为缺失值的差值结果，$x_i$为非缺失值$y_i$的下标序号。对全部缺失数据依次进行插补，直到不存在缺失值。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "\n",
    "# 自定义列向量插值函数\n",
    "\n",
    "def lagrange_ployinterp_column(s, n, k=5):\n",
    "    y = s.reindex(list(range(n - k, n)) + list(range(n + 1, n + 1 + k)))\n",
    "    y = y[y.notnull()]\n",
    "    return lagrange(y.index, list(y))(n)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# 逐个元素判断是否需要插值\n",
    "for i in data.columns:\n",
    "    for j in range(len(data)):\n",
    "        if(data[i].isnull())[j]:\n",
    "            data[i][j] = lagrange_ployinterp_column(data[i], j)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "             A           B           C\n",
      "0   235.833300  324.034300  478.323100\n",
      "1   236.270800  325.637900  515.456400\n",
      "2   238.052100  328.089700  517.090900\n",
      "3   235.906300  203.462116  514.890000\n",
      "4   236.760400  268.832400  493.352591\n",
      "5   237.151181  404.048000  486.091200\n",
      "6   237.416700  391.265200  516.233000\n",
      "7   238.656300  380.824100  493.342382\n",
      "8   237.604200  388.023000  435.350800\n",
      "9   238.031300  206.434900  487.675000\n",
      "10  235.072900  237.348072  609.193564\n",
      "11  235.531300  400.078700  660.234700\n",
      "12  235.314951  411.206900  621.234600\n",
      "13  234.468800  395.234300  611.340800\n",
      "14  235.500000  344.822100  643.086300\n",
      "15  235.635400  385.643200  642.348200\n",
      "16  234.552100  401.623400  618.197198\n",
      "17  236.000000  409.648900  602.934700\n",
      "18  235.239600  416.879500  589.345700\n",
      "19  235.489600  420.748600  556.345200\n",
      "20  236.968800  408.963200  538.347000\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "d:\\electric-leak-recognition\\venv\\lib\\site-packages\\ipykernel_launcher.py:2: FutureWarning: As the xlwt package is no longer maintained, the xlwt engine will be removed in a future version of pandas. This is the only engine in pandas that supports writing in the xls format. Install openpyxl and write to an xlsx file instead. You can set the option io.excel.xls.writer to 'xlwt' to silence this warning. While this option is deprecated and will also raise a warning, it can be globally set and the warning suppressed.\n",
      "  \n"
     ]
    }
   ],
   "source": [
    "# 输出结果\n",
    "data.to_excel(outputfile, header=None, index=False)\n",
    "\n",
    "# 打印处理后的结果\n",
    "print(data)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}